#coding:utf-8


from twisted.internet import reactor, defer, threads
from twisted.internet.protocol import Protocol, Factory, DatagramProtocol

import base
from datamethod import *
import report

class TCPProtocol(Protocol):
    def __init__(self):
        self.tel = ''
        self.index = 0
        self._link_id = None
        self.link_miss_count = 3
        
    def __del__(self):
        #report.info("this TCPServer instance has been removed: %s"%self.transport)
        pass
        
    def connectionMade(self):
        report.info("(%s,%d) connect"%self.transport.client)
        
    def dataReceived(self, data):
        report.log("Recv from %s:(%d):%s"%(self.tel, self.index, hex2str(data)))
        self.factory.deal(data, self)
            
    def sendData(self, data):
        data = self.factory.pack(data)
        self.transport.write(data)
        report.log("Send to %s:(%d):%s"%(self.tel, self.index, hex2str(data)))
        
    def loseConnection(self):
        #log.info("(%s,%d) "%self.transport.client + msg)
        self.transport.loseConnection()
        
    def connectionLost(self, reason):
        try:
            self._link_id.cancel()
        except:
            pass
        self.factory.throwIndex(self.index)
        self.factory.player.connectionLost(self.tel, self)
        if self.tel:
            report.info("tel: %s, ip:%s disconnect"%(self.tel, self.transport.client))
        else:
            report.info("(%s,%d) disconnect"%self.transport.client)

    def vehicleLogon(self, tel):
        self.tel = tel
        self.index = self.factory.fetchIndex()
        if self.index is None:
            self.loseConnection()
        reactor.callLater(1, self.linkMaintain)
        report.info("tel: %s, ip:%s login"%(self.tel, self.transport.client))
        return True

    def linkMaintain(self, interval = 0x01):
        if self.link_miss_count == 0:
            report.info("tel: %s link response has been missed for many times."%self.tel)
            self.loseConnection()
            return
        self.link_miss_count -= 1
        self.sendData([0x10, 0x84, interval])
        self._link_id = reactor.callLater(interval*60, self.linkMaintain)
        
    def linkReceived(self):
        self.link_miss_count = 3
        
    def feedData(self, busstype, bussdata):
        vehicle = vehicleTable.get(self.tel)
        if vehicle:vehicle.feedData(data)
        
class TCPDataDealMixin(base.BaseDataDeal):
    def unpack(self, data):
        datas = remove7e(hex2data(data))
        for index in range(len(datas)):
            datas[index] = untransform(datas[index])
        return datas # 转义
   
    def pack(self, data):
        checksum = getchecksum(data)
        data.insert(0, checksum)
        data = transform(data)
        return data2hex(add7e(data))

    def deal(self, data, client):
        for eachdata in self.unpack(data):
            self.separate_data(eachdata, client)
        
class TCPServer(Factory, TCPDataDealMixin):
    protocol = TCPProtocol
    def __init__(self, player):
        self.player = player
        self.count = [i for i in range(50)]
    
    def logonRequest(self, tel, client):
        client.sendData([0x10, 0x91, 0x01])
        client.vehicleLogon(tel)
        self.player.connectionCreated(tel, client)
        
    def bussDataReceived(self, bussdata, client):
        self.player.bussDataReceived(client.tel, bussdata)
    
    def linkReceived(self, data, client):
        client.linkReceived()
    
    def logoutRequest(self, data, client):
        client.sendData([0x10, 0x92, 0x01])
        self.player.connectionLost(tel, client)
        
    def fetchIndex(self):
        try:
            return self.count.pop(0)
        except IndexError:
            return None
    
    def throwIndex(self, index):
        self.count.insert(0, index)
    
    
    
    
    
    
    